using System;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.TeamArchitect.PowerTools.Features;
using Microsoft.VisualStudio.TeamArchitect.PowerTools;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System.Linq;
using System.Collections.Generic;
using System.IO;

namespace InstantFeatureBuilder
{
    class GuidanceFileDescriptor
    {
        public string NodeName;
        public string Uri;
    }

    public partial class ProcessWorkflow : GuidanceWorkflow
    {
        [Import]
        private IFeatureCompositionService FeatureComposition { get; set; }

        [Import]
        private IFxrUriReferenceService UriReferenceService { get; set; }

        /// <summary>
        /// Force all the workflow nodes to be "green" (i.e. Ready)
        /// </summary>
        public override bool IgnorePostConditions
        {
            get
            {
                return true;
            }
        }

        partial void OnPostInitialize()
        {
            GuidanceWorkflow tempWF = new GuidanceWorkflow();

            Node endOfList = null;
            //
            // Ok, we essentially ignore the auto-generated code and build our own the way we want :)
            //
            tempWF.Name = "GuidanceWorkflow";

            var initial = new Initial
            {
                Name = "Initial1",
            };

            string nodeName = string.Empty;
            string nodeLink = string.Empty;

            //
            // Note:  We couldn't use the content://./Content/... form of the URI
            // because our feature it not activated at the time this code runs
            //
            string pathToDir = this.UriReferenceService
    .ResolveUri<FeatureContent>(new Uri("content://IFB/Content/Runtime/FeatureExtensionRuntimePro.vsix")).Path;
            pathToDir = Path.Combine(Directory.GetParent(Path.GetDirectoryName(pathToDir)).FullName, "ProcessGuidance");

            List<string> sortedNames = Directory.GetFileSystemEntries(pathToDir).ToList();
            sortedNames.Sort();

            foreach (string theFn in sortedNames)
            {
                string fn = theFn;

                if (Directory.Exists(fn))
                {
                    //
                    // Create a fork/join and encapsulate the results in the FJ
                    //
                    string forkName = Path.GetFileNameWithoutExtension(fn);

                    if (forkName.IndexOf('~') > 0)
                    {
                        forkName = forkName.Substring(forkName.IndexOf('~') + 1);
                    }

                    Fork fork = new Fork
                    {
                        Name = forkName,
                    };

                    Join join = new Join
                    {
                        Name = Path.GetFileNameWithoutExtension(fn) + "_join",
                    };

                    List<string> sortedFiles = Directory.GetFiles(fn).ToList();
                    sortedFiles.Sort();

                    foreach (string theDocName in sortedFiles)
                    {
                        string docName = theDocName;

                        if (docName.ToLower().EndsWith(".link") ||
                            docName.ToLower().EndsWith(".url"))
                        {
                            if (docName.EndsWith("~.url", StringComparison.InvariantCultureIgnoreCase) ||
                                docName.EndsWith("~.link", StringComparison.InvariantCultureIgnoreCase))
                            {
                                fork.Link = File.ReadAllText(docName).Replace("\r\n", "");
                            }
                            else
                            {
                                var newGuidanceAction = new GuidanceAction
                                {
                                    Name = Path.GetFileNameWithoutExtension(docName),
                                    Link = GetLinkFromFile(docName),
                                };

                                fork.ConnectTo(newGuidanceAction);
                                newGuidanceAction.ConnectTo(join);
                            }
                        }
                        else if (docName.ToLower().EndsWith(".mht") ||
                                 docName.ToLower().EndsWith(".txt") ||
                                 docName.ToLower().EndsWith(".html"))
                        {
                            if (docName.EndsWith("~.mht", StringComparison.InvariantCultureIgnoreCase) ||
                                docName.EndsWith("~.txt", StringComparison.InvariantCultureIgnoreCase) ||
                                docName.EndsWith("~.html", StringComparison.InvariantCultureIgnoreCase))
                            {
                                fork.Link = "content://IFB/Content/ProcessGuidance/" +
                                    fn.Replace(Directory.GetParent(fn).FullName, "")
                                      .Replace(Path.DirectorySeparatorChar.ToString(), "") +
                                "/" +
                                Path.GetFileName(docName);
                            }
                            else
                            {
                                var newGuidanceAction = new GuidanceAction
                                {
                                    Name = Path.GetFileNameWithoutExtension(docName),
                                    Link = "content://IFB/Content/ProcessGuidance/" +
                                    fn.Replace(Directory.GetParent(fn).FullName, "")
                                      .Replace(Path.DirectorySeparatorChar.ToString(), "") +
                                    "/" +
                                    Path.GetFileName(docName),
                                };

                                fork.ConnectTo(newGuidanceAction);
                                newGuidanceAction.ConnectTo(join);
                            }
                        }
                    }

                    if (initial.Successors.ToList().Count == 0)
                    {
                        initial.ConnectTo(fork);
                    }
                    else
                    {
                        if (endOfList is Join)
                            ((Join)endOfList).ConnectTo(fork);
                        else
                            ((GuidanceAction)endOfList).ConnectTo(fork);
                    }
                    endOfList = join;
                }
                else
                {
                    GuidanceAction newGuidanceAction = null;
                    string docName = Path.GetFileNameWithoutExtension(fn);

                    if (docName.IndexOf('~') > 0)
                    {
                        docName = docName.Substring(docName.IndexOf('~') + 1);
                    }
                    //
                    // It's just a file
                    //
                    if (fn.ToLower().EndsWith(".url") ||
                        fn.ToLower().EndsWith(".link"))
                    {
                        newGuidanceAction = new GuidanceAction
                        {
                            Name = Path.GetFileNameWithoutExtension(fn),
                            Link = GetLinkFromFile(fn),
                        };
                    }
                    else if (fn.ToLower().EndsWith(".mht") ||
                             fn.ToLower().EndsWith(".txt") ||
                             fn.ToLower().EndsWith(".html"))
                    {
                        newGuidanceAction = new GuidanceAction
                        {
                            Name = docName,
                            Link = "content://IFB/Content/ProcessGuidance/" +
                            Path.GetFileName(fn),

                        };
                    }
                    if (initial.Successors.ToList().Count == 0)
                    {
                        initial.ConnectTo(newGuidanceAction);
                    }
                    else
                    {
                        if (endOfList is Join)
                            ((Join)endOfList).ConnectTo(newGuidanceAction);
                        else
                            ((GuidanceAction)endOfList).ConnectTo(newGuidanceAction);
                    }
                    endOfList = newGuidanceAction;
                }
            }


            var final0 = new Final
            {
                Name = "ActivityFinal1",
            };


            tempWF.ConnectTo(initial);

            if (initial.Successors.ToList().Count == 0)
            {
                var guidanceAction = new GuidanceAction
                {
                    Name = "No Guidance Documents Found",
                    Link = "content://IFB/Content/ProcessGuidance/1/Overview.mht",
                };
                initial.ConnectTo(guidanceAction);
                guidanceAction.ConnectTo(final0);
            }
            else
            {
                if (endOfList is Join)
                    ((Join)endOfList).ConnectTo(final0);
                else
                    ((GuidanceAction)endOfList).ConnectTo(final0);
            }
            INode topNode = this.Successors.ToArray<INode>()[0];
            Node originalInitialNode = topNode.Successors.ToArray<INode>()[0] as Node;

            try
            {
                if (originalInitialNode != null)
                    originalInitialNode.InsertWorkflow(tempWF, true);
            }
            catch
            {
                System.Windows.Forms.MessageBox.Show("Instant FX Runtime Error - Probable cause: an empty folder in Content\\ProcessGuidance");
            }
        }

        private string GetLinkFromFile(string fn)
        {
            string fileContents = File.ReadAllText(fn);
            int start;

            if ((start = fileContents.IndexOf("[InternetShortcut]")) >= 0)
            {                                //123456789012345678
                start += 20; // Length of [InternetShortcut] + 2 for CRLF
                int end = fileContents.Substring(start).IndexOf("\r") - 1;
                return (fileContents.Substring(start, end - start));
            }
            else
                return (fileContents.Replace("\r\n", ""));
        }

    }
}